package com.dq.controller.sys;

import com.dq.annotation.aop.SysLog;
import com.dq.context.Constant;
import com.dq.exception.customException.AdminException;
import com.dq.controller.in.base.BaseAdminQuery;
import com.dq.controller.in.user.SysUserQuery;
import com.dq.vo.ListDataVo;
import com.dq.vo.Vo;
import com.dq.vo.baseVo.VO;
import com.dq.domain.base.impl.BaseDaoImpl;

import com.dq.domain.sys.menu.SysMenu;
import com.dq.domain.sys.role.SysRole;
import com.dq.domain.sys.role.SysRoleMenu;
import com.dq.domain.sys.role.SysUserRole;
import com.dq.domain.sys.user.user.BossUser;
import com.dq.domain.sys.user.user.OrgUser;
import com.dq.domain.sys.user.user.StaffUser;
import com.dq.domain.sys.user.user.base.SysUser;
import com.dq.service.AllService;
import com.dq.service.TokenService;
import com.dq.utils.BeanNullUtil;
import com.dq.utils.TreeBuilder;
import com.dq.validator.Assert;
import com.dq.validator.ValidatorUtils;
import com.dq.validator.group.AddGroup;
import com.dq.validator.group.UpdateGroup;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 系统用户
 *
 * @author lipengjun
 * @email 939961241@qq.com
 * @date 2016年10月31日 上午10:40:10
 */
@Api(description = "用户管理(boss)")
@RestController
@RequestMapping("/sys/user/")
public class SysUserController extends AllService {
    @Autowired
    TokenService tokenService;

    @ApiOperation("所有boss用户列表")
    @PostMapping("list")
    @RequiresPermissions("sys:user:list")
//    @DataFilter(deptAlias = "sysDept")
    public Vo list(@RequestBody SysUserQuery userQuery) throws AdminException {
        //只有超级管理员，才能查看所有管理员列表
        if (shiroService.getUser().getId() != Constant.ADMIN_ID) {
            userQuery.setCreateUser(shiroService.getUser());
        }
        userQuery.format();
        //查询列表数据
        Map<String, Object> query = userQuery.parseMap();
        if (StringUtils.isNotBlank(userQuery.getUsername())) {
            query.put("username" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(userQuery.getUsername()));
            query.remove("username");
        }
        List<BossUser> list = dao.find(dao.queryAdminHql(BossUser.class, query), query);
        Long count = dao.count(dao.countAdminHql(BossUser.class, query), query);
        List<BossUser.Vo> vos = (List<BossUser.Vo>) VO.toVOCollection(list);
        return new ListDataVo(vos, count);
    }
    /**
     * 获取自身 创建的用户
     * 状态为 启用
     */
    @ApiOperation("获取下级用户")
    @PostMapping("listbypar")
    public Vo listByPar(@RequestBody SysUserQuery userQuery) throws AdminException {
        SysUser user = sysUserService.getUser();
        //只有超级管理员，才能查看所有管理员列表
        if (!sysRoleService.isAdminRole(user)) {
            userQuery.setCreateUser(shiroService.getUser());
        }
        //查询列表数据
        Map<String, Object> query = userQuery.parseMap();
        if (StringUtils.isNotBlank(userQuery.getUsername())) {
            query.put("username" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(userQuery.getUsername()));
            query.remove("username");
        }
//        query.put("isBack", true);
        query.put("status", SysUser.Status.on);

        List<BossUser> list = dao.find(dao.query2Hql(BossUser.class, query), query);
        return new Vo(VO.toVOCollection(list));
    }


    /**
     * 获取登录的用户信息
     */
    @ApiOperation("获取登录的用户信息")
    @GetMapping("info")
    public Vo<SysUser.Vo> info() {
        return new Vo(shiroService.getUser().toVO());
    }

    @ApiOperation("获取登录用户信息")
    @ResponseBody
    @PostMapping(value = "/getUserInfo")
    public Vo getUserInfo() throws AdminException {
        SysUser user = sysUserService.getUser();
        if(!(user instanceof BossUser) && !(user instanceof OrgUser) && !(user instanceof StaffUser)) {
            throw new AdminException("用户无法登录");
        }

        List<SysUserRole> sysUserRoles;
        if(String.valueOf(Constant.ADMIN_ID).equals(user.getId().toString())) {
            sysUserRoles = sysUserRoleRepository.findAll();
        }else {
            sysUserRoles = sysUserRoleRepository.findBySysUser(user);
        }

        Set<String> roleCodes = new HashSet<>(sysUserRoles.size());
        Set<SysRole> sysRoles = new HashSet<>(sysUserRoles.size());
        sysUserRoles.forEach(sysUserRole -> {
            SysRole sysRole = sysUserRole.getSysRole();
            roleCodes.add(sysRole.getCode());
            sysRoles.add(sysRole);
        });

        Set<SysMenu.Vo> menuVos = new HashSet<>();
        Set<SysMenu.Vo> buttonVos = new HashSet<>();
        if(user instanceof OrgUser || user.getId().toString().equals(String.valueOf(Constant.ADMIN_ID))) {
            SysMenu.Genre genre = null;
            if(user instanceof BossUser) {
                genre = SysMenu.Genre.boss;
            }else {
                genre = SysMenu.Genre.org;
            }
            List<SysMenu> menus = sysMenuRepository.findByDeletedIsFalseAndGenreAndStatus(genre, SysMenu.Status.on);
            menus.forEach(menu -> {
                if (menu.getType().equals(SysMenu.Type.button)) {
                    buttonVos.add((SysMenu.Vo) menu.toVO());
                } else {
                    menuVos.add((SysMenu.Vo) menu.toVO());
                }
            });
        }else {
            List<SysRoleMenu> sysRoleMenus = sysRoleMenuRepository.findBySysRoleIn(sysRoles);
            sysRoleMenus.forEach(sysRoleMenu -> {
                SysMenu sysMenu = sysRoleMenu.getSysMenu();
                if (sysMenu.getType().equals(SysMenu.Type.button)) {
                    buttonVos.add((SysMenu.Vo) sysMenu.toVO());
                } else {
                    menuVos.add((SysMenu.Vo) sysMenu.toVO());
                }
            });
        }


        if(user instanceof BossUser) {
            BossUser.Vo backUserVo = (BossUser.Vo) user.toVO();
            backUserVo.setRoleCodes(roleCodes);
            backUserVo.setMenuList(TreeBuilder.buildTree(menuVos));
            backUserVo.setButtonList(buttonVos);
            return new Vo(backUserVo);
        }else if(user instanceof OrgUser) {
            OrgUser.Vo backUserVo = (OrgUser.Vo) user.toVO();
            backUserVo.setRoleCodes(roleCodes);
            backUserVo.setMenuList(TreeBuilder.buildTree(menuVos));
            backUserVo.setButtonList(buttonVos);
            return new Vo(backUserVo);
        }else {
            StaffUser.Vo backUserVo = (StaffUser.Vo) user.toVO();
            backUserVo.setRoleCodes(roleCodes);
            backUserVo.setMenuList(TreeBuilder.buildTree(menuVos));
            backUserVo.setButtonList(buttonVos);
            return new Vo(backUserVo);
        }
    }

    @ApiOperation("保存用户(bossUser)")
    @SysLog("保存用户(bossUser)")
    @PostMapping("save")
    @RequiresPermissions("sys:user:save")
    public Vo save(@RequestBody BossUser user) throws AdminException {
        BossUser queryUser = bossUserRepository.findByUsername(user.getUsername());
        if(null!=queryUser){
            throw new AdminException("登录账号已存在");
        }
        ValidatorUtils.validateEntity(user, AddGroup.class);

        user.setPassword(sysUserService.getPassword(user.getPassword()));
        user.setCreateUser(shiroService.getUser());

        user = bossUserService.initObject(user);
        sysUserRepository.save(user);

        return new Vo(HttpStatus.OK);
    }


    @ApiOperation("修改用户(bossUser)")
    @PostMapping("update/{userId}")
    @RequiresPermissions("sys:user:update")
    public Vo update(@RequestBody BossUser user, @PathVariable @ApiParam(value = "用户id") Long userId) throws AdminException {
        if(StringUtils.isNotBlank(user.getPassword())) {
            user.setPassword(sysUserService.getPassword(user.getPassword()));
        }
        BossUser backUser = dao.get(BossUser.class, userId);
        if (backUser == null) {
            throw new AdminException("用户不存在");
        }
        BeanUtils.copyProperties(user, backUser, BeanNullUtil.getNullPropertyNames(user));

        ValidatorUtils.validateEntity(backUser, UpdateGroup.class);

        bossUserService.update(backUser);
        return new Vo(HttpStatus.OK);
    }

    /**
     * 修改自身密码
     * 需要新旧密码
     *
     * @param password
     * @param newPassword
     * @return
     * @throws AdminException
     */
    @ApiOperation("修改自身密码")
    @SysLog("修改密码")
    @PostMapping("update/pwd/{password}/{newPassword}")
    public Vo password(@ApiParam(value = "旧密码") @PathVariable(value = "password") String password,
                       @ApiParam(value = "新密码") @PathVariable(value = "newPassword") String newPassword) throws AdminException {
        Assert.isBlank(newPassword, "新密码不为能空");

        //sha256加密
        password = new Sha256Hash(password).toHex();
        //sha256加密
        newPassword = new Sha256Hash(newPassword).toHex();

        //更新密码
        BossUser sysUser = (BossUser)shiroService.getUser();
        if (!sysUser.getPassword().equals(password)) {
            throw new AdminException("原密码不正确");
        }
        sysUser.setPassword(newPassword);
        dao.save(sysUser);

        // 退出
        tokenService.deleteToken(shiroService.getToken());

        return new Vo(HttpStatus.OK);
    }
    /**
     * 修改自身密码
     * 只需新密码
     *
     * @param password
     * @return
     * @throws AdminException
     */
    @ApiOperation("修改自己密码")
    @PostMapping("update/pwd/{password}")
    public Vo updatePwd(@PathVariable String password) throws AdminException {
        BossUser user = (BossUser) shiroService.getUser();
        if (user == null) {
            throw new AdminException("用户不存在");
        }
        user.setPassword(sysUserService.getPassword(password));

        bossUserService.update(user);

        // tuichu
        tokenService.deleteToken(shiroService.getToken());
        return new Vo(HttpStatus.OK);
    }
    /**
     * 删除用户
     */
    @ApiOperation("删除用户")
    @SysLog("删除用户")
    @PostMapping("delete/{userId}")
    @RequiresPermissions("sys:user:delete")
    public Vo delete(@PathVariable @ApiParam(value = "用户id") Long userId) throws AdminException {
        if (userId == 1) {
            throw new AdminException("系统管理员不能被删除");
        }
        if (userId.equals(shiroService.getUserId())) {
            throw new AdminException("不能删除登录账号");
        }
        BossUser bossUser = dao.get(BossUser.class, userId);
        if(bossUser == null) {
            throw new AdminException("无对应账户");
        }
        bossUser.setDeleted(true);

        bossUserService.update(bossUser);
        return new Vo(HttpStatus.OK);
    }

    /**
     * 用户角色授权
     */
    @ApiOperation("用户角色授权")
    @SysLog("用户角色授权")
    @PostMapping("roleAuth/{userId}")
    @RequiresPermissions("sys:user:roleAuth")
    public Vo roleAuth(@RequestBody List<Long> roleIds, @PathVariable @ApiParam(value = "用户id") Long userId) throws
            AdminException {
        BossUser sysUser = dao.get(BossUser.class, userId);
        if (sysUser == null) {
            throw new AdminException("用户不存在");
        }
        List<SysUserRole> sysUserRoles = sysUserRoleRepository.findBySysUser(sysUser);
        if (!sysUserRoles.isEmpty()) {
            sysUserRoleRepository.deleteAll(sysUserRoles);
        }
        if (roleIds.isEmpty()) {
            return new Vo(HttpStatus.OK);
        }
        sysUserRoles = new ArrayList<>();
        List<SysRole> sysRoles = sysRoleRepository.findByIdIn(roleIds);
        for (SysRole sysRole : sysRoles) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setSysRole(sysRole);
            sysUserRole.setSysUser(sysUser);
            sysUserRoles.add(sysUserRole);
        }
        sysUserRoleRepository.saveAll(sysUserRoles);
        return new Vo(HttpStatus.OK);
    }

}
